import os
from rsa.util import AUTOMATICVARS

def merge(str1, str2):
    """ Merge two strings to create a know path. If this is not possible return None. """
    arr1 = str1.split("/")
    part1 = str2.split("/")[0]
    for i in range(1, len(arr1)):
        part2 = arr1[len(arr1) - i]
        if(part1 == part2):
            index = str1.find(part1)
            return os.path.join(str1[:index], str2)
    return os.path.join(str1, str2)

def dynamic_import(classPath):
    """ Dynamically imports a module or class from a given path. """
    rindex = classPath.rfind('.')
    package = classPath[:rindex]
    className = classPath[rindex + 1:]
    module = __import__(package, globals(), locals(), [className])
    instance = getattr(module, className)
    return instance

def clean(str, arg=True):
    """ Clean a string of unnecessary characters. """
    index = str.find("=")
    if(arg and index != -1):
        str = str[:index]
    return str.replace(' ', '').replace('"', '').replace('\n', '').replace("../", "").replace("\\","")

def get_variables(sentence):
    """ Find and returns a list of robot variables of the given sentence. """
    index = 0
    vars = []
    var_stack = []
    special_chars = "$@%"
    while index < len(sentence):
        # If here starts a variable, put this index on top of the stack
        if index < (len(sentence) - 1) and special_chars.find(sentence[index]) != -1 and sentence[index+1]== "{":
            var_stack.append(index+2)
        # If here ends a variable, recognize it and remove it from the stack
        if sentence[index] == "}" and len(var_stack) > 0:
            begin_index = var_stack.pop(len(var_stack)-1)
            var_string = sentence[begin_index:index]
            #If variable is an array, remove the sub index
            if var_string.find("[") != -1 and var_string.find("]") != -1:
                var_string = var_string[:var_string.find("[")] + var_string[var_string.rfind("]")+1:]
            #If variable searchs inside a dictionary
            if var_string.find(".get(") != -1:
                var_string = var_string[:var_string.find(".")]                
            operators = "+-*/"
            #If variable is an expression, break it ignoring digits
            if var_string.find("+")!=-1 or var_string.find("-")!=-1 or var_string.find("*")!=-1 or var_string.find("/")!=-1:
                current_token = ""
                i=0
                while i < len(var_string):
                    if operators.find(var_string[i]) != -1: # here is an operator
                        if len(current_token) > 0 and not current_token.isdigit(): #variable was read
                            if not current_token.startswith(special_chars):
                                vars.append(current_token)
                            current_token = ""  
                    elif special_chars.find(var_string[i]) !=-1: # If starts a nested var, jump it
                        i = var_string.rfind("}")
                    else: # step forward
                        current_token = current_token + var_string[i]
                    i=i+1
                if len(current_token) > 0 and not current_token.isdigit():
                    vars.append(current_token)
            else: # Variable has no operators, it's not a number and contains no vars inside
                if not var_string.isdigit():
                    # Prevents ${${${var}}}
                    while var_string.startswith("${") and var_string.endswith("}"): 
                        var_string = var_string[2:-1]
                    if var_string.find("{") == -1: # Has no vars inside
                        vars.append(var_string)
        index = index+1
    if (len(vars) > 1):
        #To Accept var names with "-"
        prueba =""
        for var in vars:
            prueba = prueba + var + "-"
        if sentence.find(prueba [:-1]) != -1:
            vars = []
            vars.append(prueba[:-1])
    return vars
    
def is_variable(str):
    """
    Returns TRUE if the string given represents a robot variable, otherwise returns FALSE
    """
    begin = str.find("${")
    end = str.find("}")
    if(begin == 0 and end == len(str) - 1):
        return True
    return False

def is_constant(str):
    """
    Returns TRUE if the string given represents a robot constant, otherwise returns FALSE
    """
    if(str in AUTOMATICVARS):
        return True
    begin = str.find("${")
    end = str.find("}")
    if(begin == 0 and end == len(str) - 1):
        value = str[begin + 2:end].lower().replace("-", "")
        if(value.isdigit()):
            return True
    return False

def element_text(node, tag):
    """
    Returns the text value of a given tag in a XML structure
    """
    result = []
    elements = node.findall(tag)
    for element in elements:
        result.append(element.text)
    if(len(result) == 1): return result[0]
    return result

def violation_reported(report, rulename, suite, description=None):
    """
    Indicates if a given violation was already reported 
    """
    violations = report.get_violations_by_rule(rulename)
    for violation in violations:
        if(violation.test.name == suite.name):
            if(not description):
                return True
            elif(violation.element == description):
                return True
    return False

def parse_option(option):
    """
    Parses a option with multiple arguments, into a list of arguments
    """
    if(not option): return None
    res = option.replace("=", "")
    if("," in res):
        return res.replace(" ", "").split(",")
    return res.split(" ")

def format_severity(severity):
    """
    Return the string code of a given severity
    """
    if(severity == 0): return "Error"
    if(severity == 1): return "Warning"
    if(severity == 2): return "Suggestion"
    return "Unknown"

def load_option(option, default=[]):
    from rsa.rulesets import OPTIONS
    if(OPTIONS.has_key(option.lower())):
        return OPTIONS[option.lower()].split(",")
    return default